
Imports System.IO
Imports System.Text

Public Module base
    Public Function ifoper(Of t)(ByVal v As Boolean, ByVal a As t, ByVal b As t) As t
        If v Then
            Return a
        Else
            Return b
        End If
    End Function

#If RETIRED Then
    Public Function ifelse(Of t)(ByVal v As Boolean, ByVal a As t, ByVal b As t) As t
        Return ifoper(v, a, b)
    End Function
#End If

    Public Function abs(ByVal i As Decimal) As Decimal
        If i >= 0 Then
            Return i
        Else
            Return -i
        End If
    End Function

    Public Function min(Of valueT)(ByVal first As valueT, ByVal second As valueT) As valueT
        If compare(first, second) < 0 Then
            Return first
        Else
            Return second
        End If
    End Function

    Public Function max(Of valueT)(ByVal first As valueT, ByVal second As valueT) As valueT
        If compare(first, second) > 0 Then
            Return first
        Else
            Return second
        End If
    End Function

    Public Sub sleep(Optional ByVal ms As Int32 = 1000)
        If ms > 0 Then
            System.Threading.Thread.Sleep(ms)
        End If
    End Sub

    Public Sub sleepSeconds(Optional ByVal s As Int32 = 1)
        sleep(secondsToMilliseconds(s))
    End Sub

    Public Sub sleepTicks(Optional ByVal t As Int64 = 10000000)
        If t > 0 Then
            System.Threading.Thread.Sleep(TimeSpan.FromTicks(t))
        End If
    End Sub

    Public Function alloc(ByVal t As Type) As Object
        On Error Resume Next

        Dim obj As Object = Nothing
        If Not t Is Nothing Then
            If t.IsArray() OrElse t.IsValueType() Then
                obj = Nothing
            Else
                Dim constructors As Reflection.ConstructorInfo() = Nothing
                constructors = t.GetConstructors()
                'save a compare here
                If constructors Is Nothing OrElse constructors.Length = 0 Then
                    obj = Nothing
                Else
                    Dim parameters(constructors(0).GetParameters().Length - 1) As Object
                    'assert vb.net will clear the array here
                    'memclr(parameters, 0, parameters.Length())
                    obj = constructors(0).Invoke(parameters)
                    'assert(Not obj Is Nothing, "allocate of type " + t.FullName + " failed")
                End If
            End If
        Else
            obj = Nothing
        End If
        Return obj
    End Function

    Public Function alloc(Of valueT)() As valueT
        Return alloc(GetType(valueT))
    End Function

    Public Function alloc(Of T)(ByVal obj As T) As T
        If obj Is Nothing Then
            Return alloc(Of T)()
        Else
            Return alloc(obj.GetType())
        End If
    End Function

    Public Sub swap(Of valueT)(ByRef this As valueT, ByRef that As valueT)
        Dim temp As valueT = Nothing
        temp = this
        this = that
        that = temp
    End Sub

    Public Function containNothing(ByVal ins As Object(), ByVal start As Int32, ByVal [end] As Int32) As Boolean
        Dim i As Int32
        For i = start To [end] - 1
            If ins(i) Is Nothing Then
                Exit For
            End If
        Next

        Return i < [end]
    End Function

    Public Function containEndOfStream(ByVal readers As StreamReader() _
                                        , ByVal start As Int32, ByVal [end] As Int32) As Boolean
        Dim i As Int32
        For i = start To [end] - 1
            If readers(i).EndOfStream Then
                Exit For
            End If
        Next

        Return i < [end]
    End Function

    Public Function createGUID() As String
        Return Guid.NewGuid().ToString()
    End Function

    Public Function createGUID(ByVal count As Int64, Optional ByVal separator As String = character.newline) As String
        Dim rtn As String = Nothing
        While count > 1
            rtn += createGUID() + separator
            count -= 1
        End While
        If count > 0 Then
            rtn += createGUID()
        End If

        Return rtn
    End Function

    Public Function inputline(ByVal s As String) As String
        Console.Write(s)
        Return Console.ReadLine
    End Function

    Public Function memorySizeDisplay(ByVal input As UInt64 _
                                    , Optional ByVal displayOriginalSize As Boolean = True _
                                    , Optional ByVal originalSizeSeperator As String _
                                    = character.leftBrace + character.rightBrace) As String
        Dim in2 As Double = input
        Static Dim unit() As String = {"B", "KB", "MB", "GB", "TB"}
        Dim i As Int32
        i = 0
        While in2 > 1024 AndAlso i < unit.Length() - 1
            in2 /= 1024
            i += 1
        End While

        Dim rtn As String = Convert.ToString(in2)
        Dim index As Int32 = rtn.IndexOf(character.dot)
        If index <> npos Then
            rtn = strleft(rtn, index + 3)
        End If
        rtn += unit(i)
        If displayOriginalSize AndAlso i > 0 Then
            If strlen(originalSizeSeperator) >= 2 Then
                rtn += character.blank + originalSizeSeperator(0) + _
                       Convert.ToString(input) + unit(0) + _
                       originalSizeSeperator(1)
            ElseIf strlen(originalSizeSeperator) = 1 Then
                rtn += character.blank + originalSizeSeperator(0) + _
                       Convert.ToString(input) + unit(0) + _
                       originalSizeSeperator(0)
            Else
                rtn += character.blank + Convert.ToString(input) + unit(0)
            End If
        End If
        Return rtn
    End Function

    Public Function sizeof(Of t)() As Int32
        Return sizeof(GetType(t))
    End Function

    Public Function sizeof(Of t)(ByVal obj As t) As Int32
        Try
            Return System.Runtime.InteropServices.Marshal.SizeOf(obj)
        Catch
            Return npos
        End Try
    End Function

    Public Function sizeof(ByVal t As Type) As Int32
        Try
            Return System.Runtime.InteropServices.Marshal.SizeOf(t)
        Catch
            Return npos
        End Try
    End Function

#If NEWRANDOM Then
    Public Function rnd() As Double
        Static seed As Double = CType(Now.Millisecond, Double) / Now.Ticks
        Static rndtimes As UInt64 = 1
        seed = (seed * rndtimes + Now.Millisecond()) / Now.Ticks
        rndtimes += 1

        Return seed
    End Function
#Else
    Public Function rnd() As Double
        Return Microsoft.VisualBasic.VBMath.Rnd()
    End Function

#If RETIRED Then
    Public Function rnd() As Double
        Dim rtn As Double
        rtn = Microsoft.VisualBasic.VBMath.Rnd()
        rtn *= ((Now.Ticks() Mod 100) \ 10) + 1
        rtn -= Int(rtn)
#If RETIRED Then
        Try
            rtn -= Convert.ToInt32(rtn)
        Catch ex As Exception
            raiseError("cannot convert rtn to int32, rtn " + Convert.ToString(rtn) + _
                       ", fallback to Microsoft.VisualBasic.VBMath.Rnd()", errorHandle.errorType.warning)
            rtn = Microsoft.VisualBasic.VBMath.Rnd()
        End Try
#End If

        Return rtn
    End Function
#End If
#End If

#If Not NEWRANDOM Then
#If PocketPC OrElse Smartphone Then
    Private Class rndtimes
        Public Shared d As UInt64
    End Class
#Else
    Private Class rndtimes
        <ThreadStatic()> Public Shared d As UInt64
    End Class
#End If
#End If

    Public Function rnd(ByVal min As Double, ByVal max As Double, Optional ByVal int As Boolean = False, _
                        Optional ByVal forceRandomize As Boolean = False) As Double
        Dim result As Double
#If Not NEWRANDOM Then
        If rndtimes.d >= 1000 OrElse rndtimes.d = 0 OrElse forceRandomize Then
            rndtimes.d = 1
            Microsoft.VisualBasic.VBMath.Randomize()
        Else
            rndtimes.d += 1
        End If
#End If

        If min > max Then
            swap(min, max)
        End If
        result = rnd() * (max - min) + min

        If int Then
            Return Microsoft.VisualBasic.Int(result)
        Else
            Return result
        End If
    End Function

    Public Function rndenchars(ByVal length As Int64, Optional ByVal careCase As Boolean = True) As String
        Dim rtn As StringBuilder = Nothing
        rtn = New StringBuilder()
        Dim i As Int64
        For i = 0 To length - 1
            rtn.Append(rndenchar(careCase))
        Next

        Return Convert.ToString(rtn)
    End Function

    Public Function rndenchar(Optional ByVal careCase As Boolean = True) As Char
        Dim c As Char = Nothing
        c = Convert.ToChar(Convert.ToInt32(rnd(Convert.ToInt32(character.a), Convert.ToInt32(character.z) + 1, True)))
        If careCase Then
            If rnd(0, 2, True) = 0 Then
                c = Char.ToUpper(c)
            End If
        End If

        Return c
    End Function

    Public Function rndbyte() As Byte
        Return rnd(0, maxInt8 + 1, True)
    End Function

    Public Function rndalpha() As Byte
        Return rnd(192, maxUInt8 + 1, True)
    End Function

    Public Function rndcolor() As Drawing.Color
#If PocketPC OrElse Smartphone Then
        Return Drawing.Color.FromArgb(rndbyte(), rndbyte(), rndbyte())
#Else
        Return Drawing.Color.FromArgb(rndalpha(), rndbyte(), rndbyte(), rndbyte())
#End If
    End Function

    Public Sub memcpy(ByVal dest As Array, ByVal deststart As Int32, _
                      ByVal src As Array, ByVal srcstart As Int32, ByVal count As Int32)
        memmove(dest, deststart, src, srcstart, count)
    End Sub

    Public Sub memmove(ByVal dest As Array, ByVal deststart As Int32, _
                       ByVal src As Array, ByVal srcstart As Int32, ByVal count As Int32)
        If count > 0 Then
            Array.Copy(src, srcstart, dest, deststart, count)
        End If
    End Sub

    Public Sub memset(ByVal dest As Array, ByVal start As Int32, ByVal count As Int32, ByVal src As Object)
        Dim i As Int32
        For i = start To start + count - 1
            dest.SetValue(src, i)
        Next
    End Sub

    Public Sub memclr(ByVal dest As Array, ByVal start As Int32, ByVal count As Int32)
        Array.Clear(dest, start, count)
    End Sub

    Public Sub memclr(ByVal dest As Array)
        memclr(dest, 0, dest.Length)
    End Sub

    Public Function memcmp(ByVal first As Array, ByVal firstStart As Int64 _
                           , ByVal second As Array, ByVal secondStart As Int64, ByVal len As Int64) As Int32
        If len = 0 Then
            Return 0
        Else
            assert(Not first Is Nothing AndAlso first.Length() >= firstStart + len _
                   , "first is not long enough to firstStart + len.")
            assert(Not second Is Nothing AndAlso second.Length() >= secondStart + len _
                   , "second is not long enough to secondStart + len.")

            Dim i As Int64
            For i = 0 To len - 1
                Dim cmp As Int64
                cmp = compare(first(i + firstStart), second(i + secondStart))
                If cmp <> 0 Then
                    Return cmp
                End If
            Next

            Return 0
        End If
    End Function

    Public Function memcmp(ByVal first As Array, ByVal second As Array, ByVal len As Int64) As Int32
        Return memcmp(first, 0, second, 0, len)
    End Function

    Public Function memcmp(ByVal first As Array, ByVal second As Array) As Int32
        If first Is Nothing AndAlso second Is Nothing Then
            Return 0
        ElseIf first Is Nothing Then
            Return -second.Length()
        ElseIf second Is Nothing Then
            Return first.Length()
        ElseIf first.Length() <> second.Length() Then
            Return first.Length() - second.Length()
        Else
            Return memcmp(first, 0, second, 0, first.Length())
        End If
    End Function

    Public Function gcd(ByVal a As Int64, ByVal b As Int64) As Int64
        If a = 0 Then
            Return b
        End If
        If b = 0 Then
            Return a
        End If
        If a < b Then
            swap(a, b)
        End If
        Dim c As Int64
        c = a Mod b
        While c > 0
            a = b
            b = c
            c = a Mod b
        End While

        Return b
    End Function

    Public Function getInvokeMethodName(ByVal invoke As [Delegate]) As String
        Return invokeMethodName(invoke)
    End Function

    Public Function invokeMethodName(ByVal invoke As [Delegate]) As String
#If PocketPC OrElse Smartphone Then
        Return "#CANNOT_GET_INVOKE_NAME#"
#Else
        Try
            Return invoke.Method.Name
        Catch
            Return "#CANNOT_GET_INVOKE_NAME#"
        End Try
#End If
    End Function

    Public ReadOnly buildInfo2 As String = applicationSign() + " is built @ " + _
                                           buildtime + " on " + buildmachine + " by " + builduser + _
                                           ", cpu-arch " + buildprocessor

    Public Sub selfincrease(Of t)(ByRef i As t, ByVal j As t)
        i = convertor.cast(Of t)(convertor.cast(Of Object)(i) + convertor.cast(Of Object)(j))
    End Sub

    Public Sub shift(ByRef b As UInt32, ByVal moves As Byte)
        assert(moves < sizeof(b) * 8, "cannot shift a variable over its size*8.")
        If moves > 0 Then
            b = (b >> moves) + ((b And (pow2(moves) - 1)) << (32 - moves))
        End If
    End Sub

    Public Function sort(Of T)(ByVal ds() As T, Optional ByVal start As Int32 = 0, _
                               Optional ByVal [end] As Int32 = npos) As Boolean
        If ds Is Nothing Then
            Return False
        ElseIf ds.Length() = 0 Then
            Return True
        End If

        If [end] = npos Then
            [end] = ds.Length()
        End If

        Try
            Array.Sort(ds, start, [end] - start)
            Return True
        Catch 'ex As Exception  'do not log here
            Return False
        End Try
    End Function

    Public Sub languageSeparate(ByVal full As String, ByRef market As String, ByRef language As String)
        If isemptystring(full) Then
            market = Nothing
            language = Nothing
        Else
            Dim index As Int64
            index = strindexof(full, network.languageSeparator, False)
            If index <> npos Then
                market = strleft(full, index)
            Else
                copy(market, full)
            End If

            index = strindexof(market, network.languageCountrySeparator, False)
            If index <> npos Then
                language = strleft(market, index)
            Else
                language = Nothing
            End If
        End If
    End Sub

    Public Function _false(ByVal ParamArray a() As Object) As Boolean
        Return False
    End Function

    Public Function _true(ByVal ParamArray a() As Object) As Boolean
        Return True
    End Function

    Public Function _inc(ByRef i As Object) As Object
        i += 1
        Return i
    End Function

    Public Function inc_(ByRef i As Object) As Object
        Dim j As Object = Nothing
        copy(j, i)
        i += 1
        Return j
    End Function

    Public Function inc(ByRef i As Object) As Object
        Return _inc(i)
    End Function

    Public Function _dec(ByRef i As Object) As Object
        i -= 1
        Return i
    End Function

    Public Function dec_(ByRef i As Object) As Object
        Dim j As Object = Nothing
        copy(j, i)
        i -= 1
        Return j
    End Function

    Public Function dec(ByRef i As Object) As Object
        Return _dec(i)
    End Function

    Public Function inc(ByRef a As Object, ByVal b As Object) As Boolean
        a += b
        Return True
    End Function

    Public Function dec(ByRef a As Object, ByVal b As Object) As Boolean
        a -= b
        Return True
    End Function

    Public Function eva(ByRef a As Object, ByVal b As Object) As Boolean
        a = b
        Return True
    End Function

    Public Function isemptyarray(Of T)(ByVal a() As T) As Boolean
        Return a Is Nothing OrElse a.Length() = 0
    End Function

    Public Function between(Of T)(ByVal i As T, ByVal l As T, ByVal u As T) As Boolean
        Return compare(i, l) > 0 AndAlso compare(i, u) < 0
    End Function

    Public Sub [erase](Of T)(ByRef a() As T)
        If Not a Is Nothing Then
            Erase a
            ReDim a(-1)
            a = Nothing
        End If
    End Sub

    Public Function paramarray_get(Of T)(ByVal index As Int64, ByRef rtn As T, ByVal needAssert As Boolean, _
                                         ByVal ParamArray ps() As Object) As Boolean
        If ps Is Nothing OrElse ps.Length() <= index Then
            If needAssert Then
                assert(False)
            End If
            Return False
        End If

        If convertor.cast(Of T)(ps(index), rtn) Then
            Return True
        Else
            If needAssert Then
                assert(False)
            End If
            Return False
        End If
    End Function

    Public Function paramarray_get(Of T)(ByVal index As Int64, ByRef rtn As T, _
                                         ByVal ParamArray ps() As Object) As Boolean
        Return paramarray_get(index, rtn, True, ps)
    End Function

    Public Function paramarray_get(Of T)(ByVal index As Int64, ByVal needAssert As Boolean, _
                                         ByVal ParamArray ps() As Object) As T
        Dim rtn As T = Nothing
        If paramarray_get(index, rtn, needAssert, ps) Then
            Return rtn
        Else
            Return Nothing
        End If
    End Function

    Public Function paramarray_get(Of T)(ByVal index As Int64, ByVal ParamArray ps() As Object) As T
        Return paramarray_get(Of T)(index, True, ps)
    End Function
End Module
